package codechicken.wirelessredstone.core;

import net.minecraft.src.*;
import java.util.*;

public class RedstoneEtherFrequency
{
	public class DimensionalNodeTracker
	{
		public TreeMap<BlockCoord, Boolean> transmittermap = new TreeMap<BlockCoord, Boolean>();
		public TreeSet<BlockCoord> receiverset = new TreeSet<BlockCoord>();
		public ArrayList<BlockCoord> recieverstoremove = new ArrayList<BlockCoord>();
		public boolean isdirty = false;
	}
	
	public RedstoneEtherFrequency(int freq)
	{
		nodetrackers = new DimensionalNodeTracker[]{new DimensionalNodeTracker(), new DimensionalNodeTracker()};
		transmittingdevices = new ArrayList<WirelessTransmittingDevice>();
		
		this.freq = freq;
	}

	public boolean isOn()
	{
		return activetransmitters > 0;
	}
	
	public void saveFreq(int dimension)
	{
		DimensionalNodeTracker nodetracker = nodetrackers[dimension];
		if(!nodetracker.isdirty)
		{
			return;
		}
		
		SaveManager.getInstance(dimension).saveFreq(freq, activetransmitters, nodetracker.transmittermap);
		nodetracker.isdirty = false;
	}
	
	public void verifyChunkTransmitters(World world, int chunkz, int chunkx)
	{
		int blockxmin = chunkx * 16;
		int blockxmax = blockxmin + 15;
		int blockzmin = chunkz * 16;
		int blockzmax = blockzmin + 15;
		int dimension = CoreProxy.getArrayDimension(world);
		
		for(Iterator<BlockCoord> iterator = nodetrackers[dimension].transmittermap.keySet().iterator(); iterator.hasNext();)
		{
			BlockCoord node = iterator.next();
			boolean on = nodetrackers[dimension].transmittermap.get(node);
			
			if(node.x >= blockxmin && node.x <= blockxmax && node.z >= blockzmin && node.z <= blockzmax)
			{
				TileEntity tile = RedstoneEther.getTile(world, node);
				if(tile == null || !(tile instanceof ITileWireless) || ((ITileWireless)tile).getFreq() != freq)
				{
					iterator.remove();
					if(on)
					{
						decrementActiveTransmitters();
					}
					nodetrackers[dimension].isdirty = true;
					System.out.println("Removed Badly Synced node at:"+node.x+","+node.y+","+node.z+" on "+freq+" in dim"+dimension);
				}
			}
		}
	}
	
	public void addReceiver(World world, BlockCoord node, int dimension)
	{
		nodetrackers[CoreProxy.getArrayDimension(world)].receiverset.add(node);
		updateReceiver(world, node, isOn());
	}
	
	public void remTransmitter(World world, BlockCoord node, int dimension)
	{
		Boolean wason = nodetrackers[dimension].transmittermap.get(node);
		nodetrackers[dimension].transmittermap.remove(node);

		if(wason != null && wason)
		{
			decrementActiveTransmitters();
			nodetrackers[dimension].isdirty = true;
		}
	}

	public void remReceiver(World world, BlockCoord node, int dimension)
	{
		if(updating)
		{
			nodetrackers[dimension].recieverstoremove.add(node);
		}
		else
		{
			nodetrackers[dimension].receiverset.remove(node);
		}
	}
	
	public void loadTransmitter(BlockCoord node, int dimension)
	{
		nodetrackers[dimension].transmittermap.put(node, true);
		activetransmitters++;
	}

	public void setTransmitter(World world, BlockCoord node, int dimension, boolean on)
	{
		Boolean wasnodeon = nodetrackers[dimension].transmittermap.get(node);
		boolean newtransmitter = wasnodeon == null;// if the get returned null the transmitter needsadding to the list

		nodetrackers[dimension].transmittermap.put(node, on);

		if(!newtransmitter && (on == wasnodeon))
		{
			return;
		}

		if(newtransmitter)
		{
			if(on)
			{
				incrementActiveTransmitters();
				nodetrackers[dimension].isdirty = true;
			}
		}
		else
		{
			if(on)
			{
				incrementActiveTransmitters();
				nodetrackers[dimension].isdirty = true;
			}
			else
			{
				decrementActiveTransmitters();
				nodetrackers[dimension].isdirty = true;
			}
		}
	}

	public void incrementActiveTransmitters()
	{
		activetransmitters++;
		if(activetransmitters == 1)// we just added the first one and it was off before
		{
			updateAllReceivers();
		}
	}

	public void decrementActiveTransmitters()
	{
		activetransmitters--;
		if(activetransmitters == 0)//we just turned the freq off
		{
			updateAllReceivers();
		}
	}
	
	public void updateAllReceivers()
	{
		if(!CoreProxy.isSMP())
		{
			updateAllReceivers(CoreProxy.getWorld());
			return;
		}
		
		for(int dimension = 0; dimension < 2; dimension++)
		{
			updateAllReceivers(CoreProxy.getWorld(dimension));
		}
	}

	public void updateAllReceivers(World world)
	{
		boolean on = isOn();
		int dimension = CoreProxy.getArrayDimension(world);
		
		RedstoneEther.updateReceivingDevices(freq, on);
		
		updating = true;
		for(Iterator<BlockCoord> iterator = nodetrackers[dimension].receiverset.iterator(); iterator.hasNext();)
		{
			updateReceiver(world, iterator.next(), on);
		}
		updating = false;
		
		if(nodetrackers[dimension].recieverstoremove.size() != 0)
		{
			for(Iterator<BlockCoord> iterator = nodetrackers[dimension].recieverstoremove.iterator(); iterator.hasNext();)
			{
				nodetrackers[dimension].receiverset.remove(iterator.next());
				iterator.remove();
			}
		}
	}

	public void updateReceiver(World world, BlockCoord node, boolean on)
	{
		ITileReceiver tileentity = (ITileReceiver) RedstoneEther.getTile(world, node);
		if(tileentity == null)
		{
			System.out.println("Null Receiver");
			return;
		}
		tileentity.setActive(on);
	}
	
	public void setColour(int colourid)
	{
		colour = colourid;
		SaveManager.getInstance(0).saveFreqInfo(freq, colour, name);
	}
	
	public int getColourId()
	{
		return colour;
	}
	
	public void setName(String name)
	{
		this.name = name;
		SaveManager.getInstance(0).saveFreqInfo(freq, colour, name);
	}
	
	public String getName()
	{
		return name;
	}
	
	public boolean isDirty(int dimension)
	{
		return nodetrackers[dimension].isdirty;
	}
	
	public void setClean(int dimension)
	{
		nodetrackers[dimension].isdirty = false;
	}
	
	public int nodeCount()
	{
		return nodetrackers[0].transmittermap.size() + nodetrackers[0].receiverset.size() + 
				nodetrackers[1].transmittermap.size() + nodetrackers[1].receiverset.size();
	}
	
	public TreeSet<BlockCoord> getReceivers(int dimension)
	{
		return nodetrackers[dimension].receiverset;
	}
	
	public TreeMap<BlockCoord, Boolean> getTransmitters(int dimension)
	{
		return nodetrackers[dimension].transmittermap;
	}
	
	public void addTransmittingDevice(WirelessTransmittingDevice device)
	{
		if(transmittingdevices.add(device))
		{
			incrementActiveTransmitters();
		}
	}
	
	public void removeTransmittingDevice(WirelessTransmittingDevice device)
	{
		if(transmittingdevices.remove(device))
		{
			decrementActiveTransmitters();
		}
	}
	
	public List<WirelessTransmittingDevice> getTransmittingDevices()
	{
		return transmittingdevices;
	}
	
	public void putActiveTransmittersInList(int dimension, ArrayList<FreqBlockCoord> txnodes)
	{
		DimensionalNodeTracker nodetracker = nodetrackers[dimension];
		for(Iterator<BlockCoord> iterator = nodetracker.transmittermap.keySet().iterator(); iterator.hasNext();)
		{
			BlockCoord node = iterator.next();
			if(nodetracker.transmittermap.get(node))
			{
				txnodes.add(new FreqBlockCoord(node, freq));
			}
		}
	}
	
	public int getActiveTransmitters()
	{
		return activetransmitters;
	}
	
	private DimensionalNodeTracker nodetrackers[] = new DimensionalNodeTracker[2];
	private ArrayList<WirelessTransmittingDevice> transmittingdevices;
	
	private boolean updating = false;
	
	private int colour = -1;
	private String name = "";
	
	private int activetransmitters;
	private int freq;
}
